package com.htg.tdtwebapi;

import android.util.Log;

import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import java.io.Serializable;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

public class TdtApiDrivingPlanning extends TdtWebApi {

    public static final String url = "http://api.tianditu.gov.cn/drive";


    public TdtApiDrivingPlanning(String key) {
        super(key);
    }

    /**
     * @param orig  起点经纬度
     * @param dest  终点经纬度
     * @param mid   途径点经纬度字符串	    途径点字符串格式：116.35506,39.92277;116.35506,39.92277两个坐标之间以分号隔开，坐标xy之间用逗号隔开(都是半角)。
     * @param style 默认0 （0：最快路线，1：最短路线，2：避开高速，3：步行）
     * @return
     * @throws Exception
     */
    public String plan(String orig, String dest, String mid, String style) throws Exception {
        //
        boolean legal = isParamsLegal(orig, dest);
        if (!legal)
            throw new Exception("orig,dest 为必填参数 不能为null 也不能为空串");
        //
        Map<String, Object> params = new HashMap<>();
        params.put("type", "search");
        params.put("tk", key);
        //
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("orig", orig);
        jsonObject.put("dest", dest);
        if (mid != null && !mid.isEmpty()) {
            jsonObject.put("mid", mid);
        }
        if (style != null && !style.isEmpty()) {
            jsonObject.put("style", style);
        }
        params.put("postStr", jsonObject.toString());
        String response = get(url, params);
        return response;
    }


    /**
     * @param orig  起点经纬度
     * @param dest  终点经纬度
     * @param mid   途径点经纬度字符串	    途径点字符串格式：116.35506,39.92277;116.35506,39.92277两个坐标之间以分号隔开，坐标xy之间用逗号隔开(都是半角)。
     * @param style 默认0 （0：最快路线，1：最短路线，2：避开高速，3：步行）
     * @return
     * @throws Exception
     */
    public Result plan2(String orig, String dest, String mid, String style) throws Exception {
        //
        String response = plan(orig, dest, mid, style);
        //
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        Document document = documentBuilder.parse(new InputSource(new StringReader(response)));
        Element root = document.getDocumentElement();
        NodeList nodeList = root.getChildNodes();

        Result result = new Result();

        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element element = (Element) node;
                String nodeName = element.getNodeName();
                if (nodeName.equals("parameters")) {
                    Parameters parameters = new Parameters();
                    NodeList childNodes = element.getChildNodes();
                    for (int j = 0; j < childNodes.getLength(); j++) {
                        Node item = childNodes.item(j);
                        if (item.getNodeType() == Node.ELEMENT_NODE) {
                            Element elementItem = (Element) item;
                            String nodeNameItem = elementItem.getNodeName();
                            if (nodeNameItem.equals("orig")) {
                                parameters.setOrig(elementItem.getTextContent());
                            } else if (nodeNameItem.equals("dest")) {
                                parameters.setDest(elementItem.getTextContent());
                            } else if (nodeNameItem.equals("mid")) {
                                parameters.setMid(elementItem.getTextContent());
                            } else if (nodeNameItem.equals("key")) {
                                parameters.setKey(elementItem.getTextContent());
                            } else if (nodeNameItem.equals("width")) {
                                parameters.setWidth(elementItem.getTextContent());
                            } else if (nodeNameItem.equals("height")) {
                                parameters.setHeight(elementItem.getTextContent());
                            } else if (nodeNameItem.equals("style")) {
                                parameters.setStyle(elementItem.getTextContent());
                            } else if (nodeNameItem.equals("version")) {
                                parameters.setVersion(elementItem.getTextContent());
                            } else if (nodeNameItem.equals("sort")) {
                                parameters.setSort(elementItem.getTextContent());
                            }
                        }
                    }
                    result.setParameters(parameters);
                } else if (nodeName.equals("routes")) {
                    Route route = new Route();

                    String count = element.getAttribute("count");
                    String time = element.getAttribute("time");
                    route.setCount(count);
                    route.setTime(time);
                    NodeList childNodes = element.getChildNodes();
                    List<RouteItem> routeItems = new ArrayList<>();
                    for (int j = 0; j < childNodes.getLength(); j++) {
                        Node child = childNodes.item(j);
                        if (child.getNodeType() == Node.ELEMENT_NODE) {
                            Element elementChild = (Element) child;
                            NodeList itemItems = elementChild.getChildNodes();
                            RouteItem routeItem = new RouteItem();
                            for (int k = 0; k < itemItems.getLength(); k++) {
                                Node itemItem = itemItems.item(k);
                                if (itemItem.getNodeType() == Node.ELEMENT_NODE) {
                                    Element elementItemItem = (Element) itemItem;
                                    String nodeNameItemItem = elementItemItem.getNodeName();
                                    String textContentItemItem = elementItemItem.getTextContent();
                                    if (nodeNameItemItem.equals("strguide")) {
                                        routeItem.setStrguide(textContentItemItem);
                                    } else if (nodeNameItemItem.equals("signage")) {
                                        routeItem.setSignage(textContentItemItem);
                                    } else if (nodeNameItemItem.equals("streetName")) {
                                        routeItem.setStreetName(textContentItemItem);
                                    } else if (nodeNameItemItem.equals("nextStreetName")) {
                                        routeItem.setNextStreetName(textContentItemItem);
                                    } else if (nodeNameItemItem.equals("tollStatus")) {
                                        routeItem.setTollStatus(textContentItemItem);
                                    } else if (nodeNameItemItem.equals("turnlatlon")) {
                                        routeItem.setTurnlatlon(textContentItemItem);
                                    }
                                }
                            }
                            routeItems.add(routeItem);
                        }
                    }
                    route.setItems(routeItems);
                    result.setRoute(route);
                } else if (nodeName.equals("simple")) {
                    Simple simple = new Simple();
                    NodeList childNodes = element.getChildNodes();
                    List<SimpleItem> simpleItems = new ArrayList<>();
                    for (int j = 0; j < childNodes.getLength(); j++) {
                        Node child = childNodes.item(j);
                        if (child.getNodeType() == Node.ELEMENT_NODE) {
                            Element elementChild = (Element) child;
                            NodeList itemItems = elementChild.getChildNodes();
                            SimpleItem simpleItem = new SimpleItem();
                            for (int k = 0; k < itemItems.getLength(); k++) {
                                Node itemItem = itemItems.item(k);
                                if (itemItem.getNodeType() == Node.ELEMENT_NODE) {
                                    Element elementItemItem = (Element) itemItem;
                                    String nodeNameItemItem = elementItemItem.getNodeName();
                                    String textContentItemItem = elementItemItem.getTextContent();
                                    if (nodeNameItemItem.equals("strguide")) {
                                        simpleItem.setStrguide(textContentItemItem);
                                    } else if (nodeNameItemItem.equals("streetNames")) {
                                        simpleItem.setStreetNames(textContentItemItem);
                                    } else if (nodeNameItemItem.equals("lastStreetName")) {
                                        simpleItem.setLastStreetName(textContentItemItem);
                                    } else if (nodeNameItemItem.equals("linkStreetName")) {
                                        simpleItem.setLinkStreetName(textContentItemItem);
                                    } else if (nodeNameItemItem.equals("signage")) {
                                        simpleItem.setSignage(textContentItemItem);
                                    } else if (nodeNameItemItem.equals("tollStatus")) {
                                        simpleItem.setTollStatus(textContentItemItem);
                                    } else if (nodeNameItemItem.equals("turnlatlon")) {
                                        simpleItem.setTurnlatlon(textContentItemItem);
                                    } else if (nodeNameItemItem.equals("streetLatLon")) {
                                        simpleItem.setStreetLatLon(textContentItemItem);
                                    } else if (nodeNameItemItem.equals("streetDistance")) {
                                        simpleItem.setStreetDistance(textContentItemItem);
                                    } else if (nodeNameItemItem.equals("segmentNumber")) {
                                        simpleItem.setSegmentNumber(textContentItemItem);
                                    }
                                }
                            }
                            simpleItems.add(simpleItem);
                        }

                    }
                    simple.setItems(simpleItems);
                    result.setSimple(simple);
                } else if (nodeName.equals("distance")) {
                    result.setDistance(element.getTextContent());
                } else if (nodeName.equals("duration")) {
                    result.setDuration(element.getTextContent());
                } else if (nodeName.equals("routelatlon")) {
                    result.setRoutelatlon(element.getTextContent());
                } else if (nodeName.equals("mapinfo")) {
                    Mapinfo mapinfo = new Mapinfo();
                    NodeList childNodes = element.getChildNodes();
                    for (int j = 0; j < childNodes.getLength(); j++) {
                        Node item = childNodes.item(j);
                        if (item.getNodeType() == Node.ELEMENT_NODE) {
                            Element elementItem = (Element) item;
                            String nodeNameItem = elementItem.getNodeName();
                            if (nodeNameItem.equals("center")) {
                                mapinfo.setCenter(elementItem.getTextContent());
                            } else if (nodeNameItem.equals("scale")) {
                                mapinfo.setScale(elementItem.getTextContent());
                            }
                        }
                    }
                    result.setMapinfo(mapinfo);
                }
            }

        }


        return result;
    }

    public class Result implements Serializable {
        private Parameters parameters;
        private Route route;
        private Simple simple;
        private String distance;
        private String duration;
        private String routelatlon;
        private Mapinfo mapinfo;


        public Parameters getParameters() {
            return parameters;
        }

        public void setParameters(Parameters parameters) {
            this.parameters = parameters;
        }

        public Route getRoute() {
            return route;
        }

        public void setRoute(Route route) {
            this.route = route;
        }

        public Simple getSimple() {
            return simple;
        }

        public void setSimple(Simple simple) {
            this.simple = simple;
        }

        public String getDistance() {
            return distance;
        }

        public void setDistance(String distance) {
            this.distance = distance;
        }

        public String getDuration() {
            return duration;
        }

        public void setDuration(String duration) {
            this.duration = duration;
        }

        public String getRoutelatlon() {
            return routelatlon;
        }

        public void setRoutelatlon(String routelatlon) {
            this.routelatlon = routelatlon;
        }

        public Mapinfo getMapinfo() {
            return mapinfo;
        }

        public void setMapinfo(Mapinfo mapinfo) {
            this.mapinfo = mapinfo;
        }
    }

    public class Parameters implements Serializable {
        private String orig;
        private String dest;
        private String mid;
        private String key;
        private String width;
        private String height;
        private String style;
        private String version;
        private String sort;

        public String getOrig() {
            return orig;
        }

        public void setOrig(String orig) {
            this.orig = orig;
        }

        public String getDest() {
            return dest;
        }

        public void setDest(String dest) {
            this.dest = dest;
        }

        public String getMid() {
            return mid;
        }

        public void setMid(String mid) {
            this.mid = mid;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getWidth() {
            return width;
        }

        public void setWidth(String width) {
            this.width = width;
        }

        public String getHeight() {
            return height;
        }

        public void setHeight(String height) {
            this.height = height;
        }

        public String getStyle() {
            return style;
        }

        public void setStyle(String style) {
            this.style = style;
        }

        public String getVersion() {
            return version;
        }

        public void setVersion(String version) {
            this.version = version;
        }

        public String getSort() {
            return sort;
        }

        public void setSort(String sort) {
            this.sort = sort;
        }
    }

    public class Route implements Serializable {
        private String count;
        private String time;
        private List<RouteItem> items;

        public String getCount() {
            return count;
        }

        public void setCount(String count) {
            this.count = count;
        }

        public String getTime() {
            return time;
        }

        public void setTime(String time) {
            this.time = time;
        }

        public List<RouteItem> getItems() {
            return items;
        }

        public void setItems(List<RouteItem> items) {
            this.items = items;
        }
    }


    public class RouteItem implements Serializable {
        private String strguide;
        private String signage;
        private String streetName;
        private String nextStreetName;
        private String tollStatus;
        private String turnlatlon;

        public String getStrguide() {
            return strguide;
        }

        public void setStrguide(String strguide) {
            this.strguide = strguide;
        }

        public String getSignage() {
            return signage;
        }

        public void setSignage(String signage) {
            this.signage = signage;
        }

        public String getStreetName() {
            return streetName;
        }

        public void setStreetName(String streetName) {
            this.streetName = streetName;
        }

        public String getNextStreetName() {
            return nextStreetName;
        }

        public void setNextStreetName(String nextStreetName) {
            this.nextStreetName = nextStreetName;
        }

        public String getTollStatus() {
            return tollStatus;
        }

        public void setTollStatus(String tollStatus) {
            this.tollStatus = tollStatus;
        }

        public String getTurnlatlon() {
            return turnlatlon;
        }

        public void setTurnlatlon(String turnlatlon) {
            this.turnlatlon = turnlatlon;
        }
    }

    public class Simple implements Serializable {
        private List<SimpleItem> items;

        public List<SimpleItem> getItems() {
            return items;
        }

        public void setItems(List<SimpleItem> items) {
            this.items = items;
        }
    }


    public class SimpleItem implements Serializable {
        private String strguide;
        private String streetNames;
        private String lastStreetName;
        private String linkStreetName;
        private String signage;
        private String tollStatus;
        private String turnlatlon;
        private String streetLatLon;
        private String streetDistance;
        private String segmentNumber;


        public String getStrguide() {
            return strguide;
        }

        public void setStrguide(String strguide) {
            this.strguide = strguide;
        }

        public String getStreetNames() {
            return streetNames;
        }

        public void setStreetNames(String streetNames) {
            this.streetNames = streetNames;
        }

        public String getLastStreetName() {
            return lastStreetName;
        }

        public void setLastStreetName(String lastStreetName) {
            this.lastStreetName = lastStreetName;
        }

        public String getLinkStreetName() {
            return linkStreetName;
        }

        public void setLinkStreetName(String linkStreetName) {
            this.linkStreetName = linkStreetName;
        }

        public String getSignage() {
            return signage;
        }

        public void setSignage(String signage) {
            this.signage = signage;
        }

        public String getTollStatus() {
            return tollStatus;
        }

        public void setTollStatus(String tollStatus) {
            this.tollStatus = tollStatus;
        }

        public String getTurnlatlon() {
            return turnlatlon;
        }

        public void setTurnlatlon(String turnlatlon) {
            this.turnlatlon = turnlatlon;
        }

        public String getStreetLatLon() {
            return streetLatLon;
        }

        public void setStreetLatLon(String streetLatLon) {
            this.streetLatLon = streetLatLon;
        }

        public String getStreetDistance() {
            return streetDistance;
        }

        public void setStreetDistance(String streetDistance) {
            this.streetDistance = streetDistance;
        }

        public String getSegmentNumber() {
            return segmentNumber;
        }

        public void setSegmentNumber(String segmentNumber) {
            this.segmentNumber = segmentNumber;
        }
    }


    public class Mapinfo implements Serializable {
        private String center;
        private String scale;

        public String getCenter() {
            return center;
        }

        public void setCenter(String center) {
            this.center = center;
        }

        public String getScale() {
            return scale;
        }

        public void setScale(String scale) {
            this.scale = scale;
        }
    }
}
